Jersey-2.x-User-Guide

3.2. Parameter Annotations (@*Param) 参数注解

资源方法中,带有基于参数注解的注解的参数可以从请求中获取信息。前面的一个例子就是在匹配了 @Path 之后,通过 @PathParam 来获取 URL 请求中的路径参数。

@QueryParam 用于从请求 URL 的查询组件中提取查询参数。下面的例子:

Example 3.8. 查询参数

@Path("smooth")
@GET
public Response smooth(
    @DefaultValue("2") @QueryParam("step") int step,
    @DefaultValue("true") @QueryParam("min-m") boolean hasMin,
    @DefaultValue("true") @QueryParam("max-m") boolean hasMax,
    @DefaultValue("true") @QueryParam("last-m") boolean hasLast,
    @DefaultValue("blue") @QueryParam("min-color") ColorParam minColor,
    @DefaultValue("green") @QueryParam("max-color") ColorParam maxColor,
    @DefaultValue("red") @QueryParam("last-color") ColorParam lastColor) {
    ...
}

如果step的参数存在的话,那么附值给它,否则默认是 @DefaultValue定义的值 2。如果step的内容不是 32位 整型,那么会返回404错误。

用户定义了一个 JAVA 类型 ColorParam 被使用,实现如下:

Example 3.9. 自定义 JAVA 类型用作消耗请求的参数

public class ColorParam extends Color {

    public ColorParam(String s) {
        super(getRGB(s));
    }

    private static int getRGB(String s) {
        if (s.charAt(0) == '#') {
            try {
                Color c = Color.decode("0x" + s.substring(1));
                return c.getRGB();
            } catch (NumberFormatException e) {
                throw new WebApplicationException(400);
            }
        } else {
            try {
                Field f = Color.class.getField(s);
                return ((Color)f.get(null)).getRGB();
            } catch (Exception e) {
                throw new WebApplicationException(400);
            }
        }
    }
}

一般的,Java方法的参数类型的可能:

  1. 一个原始类型;
  2. 有一个构造函数接受一个字符串参数;
  3. 有一个静态方法或一个命名为 fromstring 的方法,接受字符串参数(例如:Integer.valueOf(String) 和 java.util.UUID.fromString(String));
  4. 有一个注册的实现 javax.ws.rs.ext.ParamConverterProvider JAX-RS 扩展 SPI, 返回 javax.ws.rs.ext.ParamConverter 能转化“字符串”类型的实例。或
  5. List, Set 或者 SortedSet,在T满足 2 或者 3 个以上。这样的集合是只读的。

有时参数可以包含相同名称的多个值。如果是这样的话,上面第5条可以用来获得的所有值。

如果@DefaultValue不与 @QueryParam联合使用,查询参数在请求中不存在,List, Set 或者 SortedSet将会是空值集合,设置或SortedSet,对象类型为空,Java定义的默认为原始类型。

@PathParam 和其他参数注解 @MatrixParam, @HeaderParam,@CookieParam, @FormParam 遵循与 @QueryParam一样的规则。 @MatrixParam 从 URL 路径提取信息. @HeaderParam 从 HTTP 头部提取信息。 @CookieParam从关联在 HTTP 头部的 cookies 里提取信息。

@FormParam 稍有特殊,因为它提取信息,先是请求所表示的MIME媒体类型为 application/x-www-form-urlencoded,并且符合指定的 HTML 编码的形式,正如这里所描述的。此参数提取对于 HTML 表单请求是非常有用的,例如从发布的表单数据中提取名称是 name 的参数信息:

Example 3.10. HTML表格处理

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(@FormParam("name") String name) {
    // Store the message
}

如果需要通过查询路径参数,从 Map 参数名称获取值,做法以下:

Example 3.11. 从查询参数或者路径获取 Map

@GET
public String get(@Context UriInfo ui) {
    MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
    MultivaluedMap<String, String> pathParams = ui.getPathParameters();
}

header 和 cookie 参数用法如下:

Example 3.12. 从头部参数获取 Map

@GET
public String get(@Context HttpHeaders hh) {
    MultivaluedMap<String, String> headerParams = hh.getRequestHeaders();
    Map<String, Cookie> pathParams = hh.getCookies();
}

@Context 一般可以用于获得一个Java类型关联请求或响应的上下文。

因为 form 表单参数(不像其他消息的一部分)是实体,做法如下:

Example 3.13. form 表单参数 获取 Map

@POST
@Consumes("application/x-www-form-urlencoded")
public void post(MultivaluedMap<String, String> formParams) {
    // Store the message
}

就是说,不需要@Context注解。

另一种注入是 @BeanParam 允许注入上述参数到一个 bean 。一个 bean 注明@BeanParam含任何属性和适当的参数注释(像 @PathParam)将由预期的相应请求值初始化(如果这些领域在资源类)。然后,跟将请求值(像路径参数)注入到一个构造函数参数或类属性不同的是,@BeanParam可以用于注入这种 bean 到资源或资源的方法。@BeanParam就是用这样的方式聚集更多的请求参数为一个单一的 bean 的情况。

3.14. @BeanParam 用法

public class MyBeanParam {
    @PathParam("p")
    private String pathParam;

    @MatrixParam("m")
    @Encoded
    @DefaultValue("default")
    private String matrixParam;

    @HeaderParam("header")
    private String headerParam;

    private String queryParam;

    public MyBeanParam(@QueryParam("q") String queryParam) {
    this.queryParam = queryParam;
    }

    public String getPathParam() {
    return pathParam;
    }
    ...
}

Example 3.15. 将 MyBeanParam 以参数形式注入:

@POST
public void post(@BeanParam MyBeanParam beanParam, String entity) {
    final String pathParam = beanParam.getPathParam(); // contains injected path parameter "p"
    ...
}

实例展示了@PathParam@QueryParam@MatrixParam@HeaderParam集合进一个 bean 里面。里面的 bean 注射规则如上这些注射相同。@DefaultValue是用来定义矩阵参数的默认值。同时@Encoded注释都有同样的行为,如果它是用来在资源的方法直接注入。将 bean 参数z注入到 注解为 @Singleton 的资源类域是不允许的(注射方法的参数必须替换)。

@BeanParam 可以包含所有的注入参数(@PathParam, @QueryParam,@MatrixParam, @HeaderParam , @CookieParam, @FormParam )

多个 bean 可以被注入到一个资源或方法的参数,即使他们注入相同的请求值。例如,以下是可能的:

Example 3.16. 多个 bean 注入到一个资源或方法

@POST
public void post(@BeanParam MyBeanParam beanParam, @BeanParam AnotherBean anotherBean, @PathParam("p") pathParam,
String entity) {
    // beanParam.getPathParam() == pathParam
    ...
}